package pers.cz.orm.db;

import pers.cz.common.exception.ErrorCode;
import pers.cz.common.exception.OrmException;
import pers.cz.orm.dao.dialect.DbDialect;
import utils.JefLog;
import utils.StringUtils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

/**
 * @program: Jef-orm
 * @description: 简单的数据源实现，不包含连接池,使用完毕后需要主动关闭connection
 * @author: Cheng Zhi
 * @create: 2023-10-24 16:10
 **/
public class SimpleDataSource implements DataSource {

    private static JefLog jefLog = new JefLog(SimpleDataSource.class);


    static {
        try {
            jefLog.info("加载驱动");
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
            DriverManager.registerDriver(new org.postgresql.Driver());
        } catch (SQLException e) {
            jefLog.error(e, "驱动加载异常");
        }
    }

    public Connection connection;
    private String url;
    private String username;
    private String password;
    private String driverClass;
    private int timeOut;

    private DbDialect dialect;

    private final java.util.Properties prop = new java.util.Properties();



    private SimpleDataSource() {};

    public SimpleDataSource(String url,String user,String password) {
        this.url=url;
        this.username=user;
        this.password=password;
    }

    /**
     * 设置超时时间
     * @param timeOut
     */
    public void setTimeOut(int timeOut) {
        this.timeOut = timeOut;
    }

    @Override
    public Connection getConnection() throws SQLException {
        return getConnection(username, password);
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
/*        if (this.connection != null) {
            return this.connection;
        }*/
        // initDriver();
        DriverManager.setLoginTimeout(timeOut);
        java.util.Properties info=(Properties) this.prop.clone();
        if (username != null) {
            info.put("user", username);
        }
        if (password != null) {
            info.put("password", password);
        }
        try{
            this.connection = DriverManager.getConnection(url, info);
            //this.connection.setNetworkTimeout(executor, timeout);// 设置超时时间
            return this.connection;
        }catch(SQLException e){
            jefLog.error(e,this.url);
            throw e;
        }
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {

        if (iface == null) {
            throw new NullPointerException("Interface argument must not be null!");
        }
        if (!DataSource.class.equals(iface)) {
            throw new SQLException(
                    "DataSource of type [" + getClass().getName() +
                            "] can only be unwrapped as [javax.sql.DataSource], not as ["
                            + iface.getName());
        }
        return (T) this;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {

        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    private void initDriver() {

        try {
            if (driverClass==null || driverClass.length()==0) {
                String dbType = StringUtils.split(url, ":")[1];
                String diaLectName = "";
                if (dbType.toUpperCase().equals("MYSQL")) {
                    diaLectName = "pers.cz.orm.dao.dialect.MysqlDialect";
                    // DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                } else if (dbType.toUpperCase().equals("ORACLE")) {
                    diaLectName = "pers.cz.orm.dao.dialect.OracleDialect";
                    // DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
                } else if (dbType.toUpperCase().equals("ANTDB")) {
                    diaLectName = "pers.cz.orm.dao.dialect.AntDbDialect";
                    // DriverManager.registerDriver(new org.postgresql.Driver());
                } else if (dbType.toUpperCase().equals("POSTGRESQL")) {
                    diaLectName = "pers.cz.orm.dao.dialect.PostgreSqlDialect";
                    // DriverManager.registerDriver(new org.postgresql.Driver());
                } else {
                    throw new OrmException(ErrorCode.ORM_NO_DB_DISLECT_ERROR, dbType);
                }
                Class<?> aClass = Class.forName(diaLectName);
                dialect = (DbDialect) aClass.newInstance();
                driverClass = dialect.getDriveName();
            }
        } catch (Exception e) {
            jefLog.error(e, "获取数据库方言异常");
        }

        //注册驱动
        //ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

        try {
            //Thread.currentThread().setContextClassLoader(driverClassLoaderMap.get("driver"));
            //Class.forName(driverClass);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //Thread.currentThread().setContextClassLoader(contextClassLoader);
        }

    }

    /**
     * 关闭connection
     */
    public void closeConnection() {
        if (this.connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                connection = null;
            }
        }
    }

}
